from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.serializers import DateField
from rest_framework.permissions import AllowAny
from rest_framework_extensions.cache.decorators import cache_response

from blog import serializers, filters
from blog.cache_utils import PostListKeyConstructor, PostObjectKeyConstructor, CommentListKeyConstructor
from blog.models import Tag, Category, Post, Comment


class PostViewSet(ModelViewSet):
    serializer_class = serializers.PostListSerializer
    queryset = Post.objects.all()
    # permission_classes = [AllowAny]
    serializer_class_table = {
        "list": serializers.PostListSerializer,
        "retrieve": serializers.PostRetrieveSerializer,
    }
    filter_backends = [DjangoFilterBackend]
    filter_class = filters.PostFilter

    def get_serializer_class(self):
        return self.serializer_class_table.get(
            self.action, super().get_serializer_class()
        )

    @cache_response(timeout=5 * 60, key_func=PostListKeyConstructor())
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

    # key_func      缓存key生成类
    @cache_response(timeout=5 * 60, key_func=PostObjectKeyConstructor())
    def retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

    @action(methods=["GET"], detail=False, url_path="archive/dates", url_name="archive-date")
    def list_archive_dates(self, request, *args, **kwargs):
        dates = Post.objects.dates("created_time", "month", order="DESC")
        # FORMAT
        data = [date.strftime("%Y-%m") for date in dates]
        # date_field = DateField()
        # data = [date_field.to_representation(date)[:7] for date in dates]
        return Response(data=data)

    @cache_response(timeout=5 * 60, key_func=CommentListKeyConstructor())
    @action(methods=["GET"], detail=True, url_path="comments", url_name="comment",
            serializer_class=serializers.CommentSerializer)
    def list_comments(self, request, *args, **kwargs):
        # 根据 URL 传入的参数值（文章 id）获取到博客文章记录
        post = self.get_object()
        # 获取文章下关联的全部评论
        queryset = post.comment_set.all().order_by("-created_time")
        # 对评论列表进行分页，根据 URL 传入的参数获取指定页的评论
        page = self.paginate_queryset(queryset)
        # 序列化评论
        serializer = self.get_serializer(page, many=True)
        # 返回分页后的评论列表
        return self.get_paginated_response(serializer.data)


class CategoryViewSet(ModelViewSet):
    queryset = Category.objects.all().order_by("name")
    serializer_class = serializers.CategorySerializer
    # 关闭分页
    pagination_class = None


class TagViewSet(ModelViewSet):
    queryset = Tag.objects.all().order_by("name")
    serializer_class = serializers.TagSerializer
    # 关闭分页
    pagination_class = None


class CommentViewSet(ModelViewSet):
    serializer_class = serializers.CommentSerializer

    def get_queryset(self):  # pragma: no cover
        return Comment.objects.all()

# 限流
# class PostSearchAnonRateThrottle(AnonRateThrottle):
#     THROTTLE_RATES = {"anon": "5/min"}




# class PostSearchView(HaystackViewSet):
#     index_models = [Post]
#     serializer_class = PostHaystackSerializer
#     throttle_classes = [PostSearchAnonRateThrottle]


# class ApiVersionTestViewSet(viewsets.ViewSet):  # pragma: no cover
#     @action(
#         methods=["GET"], detail=False, url_path="test", url_name="test",
#     )
#     def test(self, request, *args, **kwargs):
#         if request.version == "v1":
#             return Response(
#                 data={
#                     "version": request.version,
#                     "warning": "该接口的 v1 版本已废弃，请尽快迁移至 v2 版本",
#                 }
#             )
#         return Response(data={"version": request.version})
